import ezdxf
from OCC.Core.gp import gp_Pnt, gp_Vec
from OCC.Core.BRepBuilderAPI import BRepBuilderAPI_MakeEdge, BRepBuilderAPI_MakeWire, BRepBuilderAPI_MakeFace
from OCC.Core.BRepPrimAPI import BRepPrimAPI_MakePrism
from OCC.Core.BRepAlgoAPI import BRepAlgoAPI_Common
from OCC.Display.SimpleGui import init_display


def read_edges_2d(file_path):
    """读取 DXF 文件中的 LINE 实体，并返回 [(x1,y1), (x2,y2)] 点对列表"""
    doc = ezdxf.readfile(file_path)
    msp = doc.modelspace()
    edges = []
    seen = set()
    for e in msp:
        if e.dxftype() == 'LINE':
            try:
                s = tuple(round(float(e.dxf.start[i]), 6) for i in [0, 1])
                t = tuple(round(float(e.dxf.end[i]), 6) for i in [0, 1])
                if s == t:
                    continue
                key = tuple(sorted([s, t]))
                if key in seen:
                    continue
                seen.add(key)
                edges.append((s, t))
            except Exception as ex:
                print(f"[跳过] LINE 错误: {ex}")
    return edges


def build_face_from_2d_edges(edges_2d, plane='XY'):
    """构建 2D 面，投影到指定平面"""
    wire_builder = BRepBuilderAPI_MakeWire()
    for (x1, y1), (x2, y2) in edges_2d:
        if plane == 'XY':
            p1, p2 = gp_Pnt(x1, y1, 0), gp_Pnt(x2, y2, 0)
        elif plane == 'YZ':
            p1, p2 = gp_Pnt(0, x1, y1), gp_Pnt(0, x2, y2)
        elif plane == 'XZ':
            p1, p2 = gp_Pnt(x1, 0, y1), gp_Pnt(x2, 0, y2)
        else:
            raise ValueError("Unsupported plane type")
        wire_builder.Add(BRepBuilderAPI_MakeEdge(p1, p2).Edge())
    if not wire_builder.IsDone():
        raise RuntimeError("构建 Wire 失败：请检查是否闭环")
    return BRepBuilderAPI_MakeFace(wire_builder.Wire()).Face()


def extrude_face(face, direction: str, length: float = 100):
    """沿指定方向拉伸 2D 面形成体积"""
    if direction == 'X':
        vec = gp_Vec(length, 0, 0)
    elif direction == 'Y':
        vec = gp_Vec(0, length, 0)
    elif direction == 'Z':
        vec = gp_Vec(0, 0, length)
    else:
        raise ValueError("Invalid direction")
    return BRepPrimAPI_MakePrism(face, vec).Shape()


def main():
    # Step 1: 读取三视图
    front_edges = read_edges_2d("/home/i2-c/TestData/Output/5-1/20250525-230314/5-1.dxf")  # front: Y-Z 平面
    top_edges   = read_edges_2d("/home/i2-c/TestData/Output/5-1/20250525-230314/5-3.dxf")  # top: X-Y 平面
    side_edges  = read_edges_2d("/home/i2-c/TestData/Output/5-1/20250525-230314/5-2.dxf")  # side: X-Z 平面

    if not front_edges or not top_edges or not side_edges:
        print("某个视图未成功读取，请检查 DXF 文件内容。")
        return

    # Step 2: 构建三面
    front_face = build_face_from_2d_edges(front_edges, plane='YZ')
    top_face   = build_face_from_2d_edges(top_edges,   plane='XY')
    side_face  = build_face_from_2d_edges(side_edges,  plane='XZ')

    # Step 3: 拉伸成体积（默认最大方向为 100，可调整）
    front_vol = extrude_face(front_face, direction='X', length=100)
    top_vol   = extrude_face(top_face,   direction='Z', length=100)
    side_vol  = extrude_face(side_face,  direction='Y', length=100)

    # Step 4: 求交集（三视图构成立体）
    print("正在进行布尔交集...")
    inter12 = BRepAlgoAPI_Common(front_vol, top_vol).Shape()
    solid = BRepAlgoAPI_Common(inter12, side_vol).Shape()

    # Step 5: 显示结果
    display, start_display, *_ = init_display()
    display.DisplayShape(solid, update=True)
    start_display()


if __name__ == '__main__':
    main()
